#include "app_buffer.h"
#include "log/log.h"
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

static SubBuffer *sub_buffer_init(int total_size)
{
    SubBuffer *sub_buffer = (SubBuffer *)malloc(sizeof(SubBuffer));
    sub_buffer->ptr = malloc(total_size);
    sub_buffer->total_size = total_size;
    sub_buffer->len = 0;
    return sub_buffer;
}

Buffer *app_buffer_init(int total_size)
{
    // 分配大缓冲区内存
    Buffer *buffer = (Buffer *)malloc(sizeof(Buffer));
    //初始化2个小缓冲区，添加到大缓冲区中
    buffer->sub_buffers[0] = sub_buffer_init(total_size);
    buffer->sub_buffers[1] = sub_buffer_init(total_size);
    //初始化索引属性
    buffer->read_index = 0;
    buffer->write_index = 1;
    //初始化互斥锁 读锁和写锁
    pthread_mutex_init(&buffer->r_lock, NULL);
    pthread_mutex_init(&buffer->w_lock, NULL);

    return buffer;
}

void app_buffer_free(Buffer *buffer)
{
    //释放小缓冲区内存
    free(buffer->sub_buffers[0]->ptr);
    free(buffer->sub_buffers[1]->ptr);
    //释放小缓冲区
    free(buffer->sub_buffers[0]);
    free(buffer->sub_buffers[1]);
    //释放大缓冲区
    free(buffer);
}

static void switch_buffer(Buffer *buffer)
{
    log_debug("切换缓冲区,加锁");
    pthread_mutex_lock(&buffer->w_lock);
    int tmep = buffer->read_index;
    buffer->read_index = buffer->write_index;
    buffer->write_index = tmep;
    //解锁
    log_debug("切换缓冲区,解锁");
    pthread_mutex_unlock(&buffer->w_lock);
}

int app_buffer_write(Buffer *buffer, char *data, int data_len)
{
    if (data_len > 255)
    {
        log_error("要写入的数据长度超过255");
        return -1;
    }
    log_debug("要写入的数据:%*s,长度为%d  ,加锁" , data_len, data ,data_len);

    //加锁
    pthread_mutex_lock(&buffer->w_lock);
    
    //获取写缓冲区
    SubBuffer *w_buffer = buffer->sub_buffers[buffer->write_index];
    //判断写缓冲区是否写满
    if ( data_len > w_buffer->total_size - w_buffer->len - 1 )
    {
        log_error("写缓冲区已满,解锁");
        //解锁
        pthread_mutex_unlock(&buffer->w_lock);
        return -1;

    }
    
    //写入数据 （先写入数据长度，再写入数据）
    w_buffer->ptr[w_buffer->len] = data_len;
    memcpy(w_buffer->ptr + w_buffer->len + 1, data, data_len);
    //更新数据长度
    w_buffer->len += data_len + 1;
    //解锁
    pthread_mutex_unlock(&buffer->w_lock);

    log_debug("写入数据:%*s成功,解锁 ",data_len, data);

    return 0;
}

int app_buffer_read(Buffer *buffer, char *data_buf, int buf_size)
{
    //加锁
    pthread_mutex_lock(&buffer->r_lock);
    log_debug("准备读取数据，加锁");
    //获取读缓冲区
    SubBuffer *r_buffer = buffer->sub_buffers[buffer->read_index];

    //判断读缓冲区是否有数据 如果没有数据切换缓冲区
    if (r_buffer->len == 0)
    {
        switch_buffer(buffer);
        //获取新的读缓冲区
        r_buffer = buffer->sub_buffers[buffer->read_index];
        //判断新的读缓冲区是否有数据
        if (r_buffer->len == 0)
        {
            log_error("读缓冲区没有数据,解锁");
            //解锁
            pthread_mutex_unlock(&buffer->r_lock);
            return -1;
        }
    }
    //读取数据
    int data_len = r_buffer->ptr[0]; //读取数据长度
    log_debug("读取数据长度:%d", data_len);
    if (data_len > buf_size)
    {
        log_error("读取数据长度大于缓冲区大小,解锁");
        //解锁
        pthread_mutex_unlock(&buffer->r_lock);
        return -1;
    }
    memcpy(data_buf, r_buffer->ptr + 1, data_len); //读取数据
    memmove(r_buffer->ptr, r_buffer->ptr + data_len + 1, r_buffer->len - data_len - 1); //移动数据
    r_buffer->len -= data_len + 1; //更新数据长度

    //读取完成后，切换缓冲区
    if(r_buffer->len == 0)
    {
        switch_buffer(buffer);
    }

    //解锁
    pthread_mutex_unlock(&buffer->r_lock);
    log_debug("读取数据:%*s成功,解锁 ",data_len, data_buf);
    return data_len;
}


